<?php
namespace modules\iChat\objects;

use modules\iChat\caches\SocketCache;
use modules\iChat\libs\FS;

class Session
{
	const TYPE_USER   = 1;
	const TYPE_GROUP  = 2;
	const TYPE_SYSTEM = 3;

	const FILE_DIALOGUE_USER  = PATH_BASE . 'modules/iChat/data/dialogue-user.log';
	const FILE_DIALOGUE_GROUP = PATH_BASE . 'modules/iChat/data/dialogue-group.log';
	const FILE_DIALOGUE_HS    = PATH_BASE . 'modules/iChat/data/dialogue-history.log';

	public static $uid2Sock = [];
	public static $sock2Uid = [];
	public static function getInstance($uId, $toId, $type, $msg)
	{
		static $dialogue = [];
		$k = implode(',', func_get_args());
		if (!isset($dialogue[$k])) {
			$dialogue[$k] = new self($uId, $toId, $type, $msg);
		}
		return $dialogue[$k];
	}

	private $uId;
	private $toId;
	private $type;
	private $msg;

	public function __construct($uId, $toId, $type, $msg)
	{
		$this->type = $type;
		$this->toId = $toId;
		$this->uId  = $uId;
		$this->msg  = $msg;
	}

	public function send()
	{
		switch ($this->type) {
			case self::TYPE_USER :
				$this->sendP2P();
				break;
			case self::TYPE_GROUP :
				$this->sendP2G();
				break;
			case self::TYPE_SYSTEM :
				$this->broadCast();
				break;
		}
	}

	public function sendP2P()
	{
		//可以过滤是否好友
		if ($sock = self::getSocket($this->toId)) {//好友在线
			WebSocket::write($sock['resource'], $this->assembleNews());
		} else {//好友不在线
			//消息存储，等用户上线拉取
			$this->saveUserMessage();
		}
	}

	public function sendP2G()
	{
		$groupUserList = User::getGroupUser($this->toId);
		$notOnline = [];
		foreach ($groupUserList as $userID) {
			//可以过滤是否好友
			if ($sock = self::getSocket($userID)) {//好友在线
				WebSocket::write($sock['resource'], $this->assembleNews());
			} else {//好友不在线
				$notOnline[] = $userID;
			}
		}
		if ($notOnline) {
			//消息存储，等用户上线拉取
			$this->saveGroupMessage($notOnline);
		}
	}

	public function broadCast()
	{
		//echo "broadCast\n";
		foreach (WebSocket::$connect as $sock) {
			if ($sock['type'] == 'master') {
				continue;
			}
			WebSocket::write($sock['resource'], $this->assembleNews());
		}
	}

	public static function getSocket($id)
	{
		if (isset(self::$uid2Sock[$id])) {
			return WebSocket::$connect[self::$uid2Sock[$id]];
		}
		return [];
	}

	public function assembleNews() {
		return [
			'rid'  => $this->toId,
			'fid'  => $this->uId,
			'type' => $this->type,
			'msg'  => $this->msg,
			'time' => time(),
		];
	}

	public function saveUserMessage()
	{
		FS::puts($this->toId, $this->assembleNews(), 
			self::FILE_DIALOGUE_USER, false);
	}

	public static function saveGroupMessage(Array $userIDs)
	{
		foreach ($userIDs as $userID) {
			FS::puts($userID,  $this->assembleNews(), 
				self::FILE_DIALOGUE_GROUP, false);
		}
	}

}